package com.ssy.lingxi.search.serviceImpl;

import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.tree.Node;
import com.ssy.lingxi.common.constant.tree.TreeUtils;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.search.api.model.request.CustomerAttributeRequest;
import com.ssy.lingxi.search.api.model.request.CustomerAttributeValueRequest;
import com.ssy.lingxi.search.api.model.request.SelectSearchRequest;
import com.ssy.lingxi.search.api.model.response.AttributeResponse;
import com.ssy.lingxi.search.api.model.response.BrandResponse;
import com.ssy.lingxi.search.common.tree.CategoryNode;
import com.ssy.lingxi.search.service.IShopService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 商城实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class ShopServiceImpl implements IShopService {

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Resource
    private IRedisStringUtils redisStringUtils;

    /**
     * 查询商品分类树
     * @param selectSearchRequest
     * @return
     */
    @Override
    public List<Node> getCategoryTree(Integer type, Integer environment, SelectSearchRequest selectSearchRequest) {
        //构建查询条件
        BoolQueryBuilder queryBuilder = this.getBoolQueryBuilder(type, environment, selectSearchRequest);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //(如果storeId不能空，代表查询会员品类; 如果storeId为空，代表查询平台后台品类)
        Long storeId = selectSearchRequest.getStoreId();
        String esField;
        String redisKey;
        if(storeId != null && storeId > 0){
            esField = "customerCategory.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CUSTOMER_CATEGORY;
        }else{
            esField = "customerCategory.category.fullId.keyword";
            redisKey = Constants.REDIS_KEY_CATEGORY;
        }
        //分组
        TermsAggregationBuilder aggregationCategoryId = AggregationBuilders.terms("group_categoryId").field(esField).size(1200000);
        searchSourceBuilder.aggregation(aggregationCategoryId);
        search.source(searchSourceBuilder);
        try{
            CategoryNode categoryNode = new CategoryNode();
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_categoryId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        //将品类进行组装
                        String fullId = String.valueOf(bucket.getKey());
                        if(fullId.contains(Constants.SPLIT_STR_FULL_ID)){
                            String[] split = fullId.split(Constants.TRANSFER_STR + Constants.SPLIT_STR_FULL_ID);
                            if(split.length > 0){
                                for(int i = 0; i < split.length; i++){
                                    if(i == 0){
                                        //一级品类
                                        Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                                        rootList.add(Long.valueOf(split[i]));
                                        categoryNode.setRootList(rootList);
                                    }
                                    //所有品类
                                    Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                                    sourceList.add(Long.valueOf(split[i]));
                                    categoryNode.setSourceList(sourceList);

                                }
                            }
                        }else{
                            //商品挂在一级品类下
                            Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                            rootList.add(Long.valueOf(fullId));
                            categoryNode.setRootList(rootList);
                            //所有品类
                            Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                            sourceList.add(Long.valueOf(fullId));
                            categoryNode.setSourceList(sourceList);
                        }
                    });
                }
            }
            Map<String, String> categoryMap = redisStringUtils.hGetAll(redisKey, Constants.REDIS_PRODUCT_INDEX);
            Set<Long> rootCategoryIdList = categoryNode.getRootList();
            Set<Long> sourceCategoryIdList = categoryNode.getSourceList();
            //组装树结构
            if(rootCategoryIdList != null && !rootCategoryIdList.isEmpty()){
                List<Node> rootList = TreeUtils.getNodeList(rootCategoryIdList, categoryMap);
                List<Node> sourceList = TreeUtils.getNodeList(sourceCategoryIdList, categoryMap);
                return TreeUtils.buildTree(sourceList, rootList);
            }
            return new ArrayList<>();
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 查询商品属性
     * @return
     */
    @Override
    public List<AttributeResponse> getAttributeByCategoryId(Integer type, Integer environment, SelectSearchRequest selectSearchRequest) {
        //构建查询条件
        BoolQueryBuilder queryBuilder = this.getBoolQueryBuilder(type, environment, selectSearchRequest);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationCategoryId = AggregationBuilders.terms("group_attribute").field("commodityAttributeList.id")
              .subAggregation(AggregationBuilders.terms("group_attributeName").field("commodityAttributeList.customerAttribute.name.keyword"));
//              .subAggregation(AggregationBuilders.terms("group_attributeValue").field("commodityAttributeList.customerAttribute.customerAttributeValueList.value"));
//                ).subAggregation(AggregationBuilders.terms("group_attributeName").field("commodityAttributeList.customerAttribute.name.keyword"));


        searchSourceBuilder.aggregation(aggregationCategoryId).size(1200000);
        search.source(searchSourceBuilder);
        try{
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms attributeIdTerms = aggregations.get("group_attribute");
                List<? extends Terms.Bucket> brandBuckets = attributeIdTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(attributeIdBucket -> {
                        Terms attributeNameTerms = attributeIdBucket.getAggregations().get("group_attributeName");
                        List<? extends Terms.Bucket> attributeBuckets = attributeNameTerms.getBuckets();
                        if(attributeBuckets != null){
                            attributeBuckets.forEach(attributeNameBucket -> {
                                Terms attributeValueIdTerms = attributeNameBucket.getAggregations().get("group_attributeValueId");
                                List<? extends Terms.Bucket> brandLogoUrlBuckets = attributeValueIdTerms.getBuckets();
                                brandLogoUrlBuckets.forEach(attributeValueIdBucke -> {
                                    Terms attributeValueTerms = attributeValueIdBucke.getAggregations().get("group_attributeValue");
                                    List<? extends Terms.Bucket> attributeValueBuckets = attributeValueTerms.getBuckets();
                                    attributeValueBuckets.forEach(attributeValueBucke -> System.out.println(attributeIdBucket.getKeyAsString() + ":" + attributeNameBucket.getKeyAsString() + ":" + attributeValueIdBucke.getKeyAsString() + ":" + attributeValueBucke.getKeyAsString()));
                                });
                            });
                        }
                    });
                }

                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        //将品类进行组装
                        String fullId = String.valueOf(bucket.getKey());
                    });
                }
            }
            return new ArrayList<>();
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 查询商品品牌
     * @return
     */
    @Override
    public List<BrandResponse> getBrand(Integer type, Integer environment, SelectSearchRequest selectSearchRequest) {
        List<BrandResponse> brandList = new ArrayList<>();
        //构建查询条件
        BoolQueryBuilder queryBuilder = this.getBoolQueryBuilder(type, environment, selectSearchRequest);
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationBrandId = AggregationBuilders.terms("group_brandId").field("brand.id").size(1200000)
                .subAggregation(AggregationBuilders.terms("group_brandName").field("brand.name.keyword").subAggregation(AggregationBuilders.terms("group_brandLogoUrl").field("brand.logoUrl.keyword")));
        searchSourceBuilder.aggregation(aggregationBrandId);
        search.source(searchSourceBuilder);
        //搜索
        try{
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_brandId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        Terms brandNameTerms = bucket.getAggregations().get("group_brandName");
                        List<? extends Terms.Bucket> brandNameBuckets = brandNameTerms.getBuckets();
                        if(brandNameBuckets != null){
                            brandNameBuckets.forEach(bucketName -> {
                                Terms brandLogoUrlTerms = bucketName.getAggregations().get("group_brandLogoUrl");
                                List<? extends Terms.Bucket> brandLogoUrlBuckets = brandLogoUrlTerms.getBuckets();
                                brandLogoUrlBuckets.forEach(bucketLogoUrl -> {
                                    BrandResponse brand = new BrandResponse();
                                    brand.setId(Long.valueOf(String.valueOf(bucket.getKey())));
                                    brand.setName(String.valueOf(bucketName.getKey()));
                                    brand.setLogoUrl(String.valueOf(bucketLogoUrl.getKey()));
                                    brandList.add(brand);
                                });
                            });
                        }
                    });
                }
            }
            return brandList;
        }catch (Exception e){
            return new ArrayList<>();
        }
    }

    /**
     * 构建查询条件
     * @param type
     * @param environment
     * @param selectSearchRequest
     * @return
     */
    private BoolQueryBuilder getBoolQueryBuilder(Integer type, Integer environment, SelectSearchRequest selectSearchRequest){
        //获取参数
        Long storeId = selectSearchRequest.getStoreId();
        Long brandId = selectSearchRequest.getBrandId();
        Long categoryId = selectSearchRequest.getCategoryId();
        List<CustomerAttributeRequest> customerAttributeList = selectSearchRequest.getCustomerAttributeList();
        String provinceCode = selectSearchRequest.getProvinceCode();
        String cityCode = selectSearchRequest.getCityCode();
        List<Integer> priceTypeList = selectSearchRequest.getPriceTypeList();
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        //如果storeId不能空，代表查询会员品类; 如果storeId为空，代表查询平台后台品类
        String attributeKey = null;
        String attributeValueKey = null;
        if(storeId != null && storeId >0){
            //店铺
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
            //品类
            if(categoryId != null && categoryId > 0){
                String categoryKey = "customerCategory.fullId:*";
                queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, categoryId) + "*"));
                // 拼接属性搜索
                attributeKey = "unitPricePicList.attributeAndValueList.customerAttribute.id";
                attributeValueKey = "unitPricePicList.attributeAndValueList.customerAttributeValue.id";
            }
        }else{
            if(categoryId != null && categoryId > 0){
                String categoryKey = "customerCategory.category.fullId:*";
                queryBuilder.must(QueryBuilders.queryStringQuery(categoryKey + String.format(Constants.CATEGORY_FULL_ID_NUM, categoryId) + "*"));
                // 拼接属性搜索
                attributeKey = "unitPricePicList.attributeAndValueList.customerAttribute.attribute.id";
                attributeValueKey = "unitPricePicList.attributeAndValueList.customerAttributeValue.attributeValue.id";
            }
        }

        //属性
        if(customerAttributeList != null && !customerAttributeList.isEmpty()){
            BoolQueryBuilder customerAttributeQueryBuilder = QueryBuilders.boolQuery();
            String finalAttributeKey = attributeKey;
            String finalAttributeValueKey = attributeValueKey;
            customerAttributeList.forEach(customerAttribute -> {
                Long customerAttributeId = customerAttribute.getCustomerAttributeId();
                List<CustomerAttributeValueRequest> customerAttributeValueList = customerAttribute.getCustomerAttributeValueList();
                customerAttributeValueList.forEach(customerAttributeValue -> {
                    Long customerAttributeValueId = customerAttributeValue.getId();
                    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
                    boolQueryBuilder.must(QueryBuilders.termQuery(finalAttributeKey, customerAttributeId));
                    boolQueryBuilder.must(QueryBuilders.termQuery(finalAttributeValueKey, customerAttributeValueId));
                    customerAttributeQueryBuilder.should(boolQueryBuilder);
                });
            });
            queryBuilder.must(customerAttributeQueryBuilder);
        }

        // 拼接品牌搜索
        if(brandId != null && brandId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("brand.id", brandId));
        }

        // 拼接省份搜索
        if(StringUtils.isNotEmpty(provinceCode)){
            BoolQueryBuilder province = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("isAllArea", false)).must(QueryBuilders.matchQuery("commodityAreaList.provinceCode", provinceCode));
            queryBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("isAllArea", true)).should(province));
        }

        // 拼接城市搜索
        if(StringUtils.isNotEmpty(cityCode)){
            BoolQueryBuilder city = QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("commodityAreaList.isAllCity", false)).must(QueryBuilders.matchQuery("commodityAreaList.cityCode", cityCode));
            queryBuilder.must(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("isAllArea", true)).should(QueryBuilders.matchQuery("commodityAreaList.isAllCity", true)).should(city));
        }

        // 拼接定价方式搜索
        if(priceTypeList != null && !priceTypeList.isEmpty()){
            queryBuilder.must(QueryBuilders.termsQuery("priceType", priceTypeList));
        }

        // 按商城环境
        if(type != null && type > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.type", type));
        }
        if(environment != null && environment > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.environment", environment));
        }

        return queryBuilder;
    }
}